/*
 * Copyright (c) 2010-2020 Belledonne Communications SARL.
 *
 * This file is part of linphone-android
 * (see https://www.linphone.org).
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package com.newlink.building.activities.main.history.viewmodels

import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.newlink.building.NL_App.Companion.coreContext
import com.newlink.building.utils.Module_Phone_Event
import com.newlink.building.activities.main.history.data.Module_Phone_GroupedCallLogData
import com.newlink.building.compatibility.ContactsUpdatedListenerStub
import com.newlink.building.utils.Module_Phone_LinphoneUtils
import org.linphone.core.*
import org.linphone.core.tools.Log

class Module_Phone_CallLogsListViewModel : ViewModel() {
    val callLogs = MutableLiveData<ArrayList<Module_Phone_GroupedCallLogData>>()
    val callLogsSortByName = MutableLiveData<ArrayList<Module_Phone_GroupedCallLogData>>()
    val missedCallLogs = MutableLiveData<ArrayList<Module_Phone_GroupedCallLogData>>()
    val outgoingCallLogs = MutableLiveData<ArrayList<Module_Phone_GroupedCallLogData>>()

    val displayCallLogs = MutableLiveData<ArrayList<Module_Phone_GroupedCallLogData>>()
    val displayCallLogsSortByName = MutableLiveData<ArrayList<Module_Phone_GroupedCallLogData>>()
    val displayMissedCallLogs = MutableLiveData<ArrayList<Module_Phone_GroupedCallLogData>>()
    val displayOutgoingCallLogs = MutableLiveData<ArrayList<Module_Phone_GroupedCallLogData>>()

    val missedCallLogsSelected = MutableLiveData<Boolean>()

    val contactsUpdatedEvent: MutableLiveData<Module_Phone_Event<Boolean>> by lazy {
        MutableLiveData<Module_Phone_Event<Boolean>>()
    }

    private val listener: CoreListenerStub = object : CoreListenerStub() {
        override fun onCallStateChanged(
            core: Core,
            call: Call,
            state: Call.State,
            message: String
        ) {
            updateCallLogs()
        }
    }

    private val contactsUpdatedListener = object : ContactsUpdatedListenerStub() {
        override fun onContactsUpdated() {
            Log.i("[Call Logs] Contacts have changed")
            contactsUpdatedEvent.value = Module_Phone_Event(true)
        }
    }

    init {
        missedCallLogsSelected.value = false
        updateCallLogs()

        coreContext.core.addListener(listener)
        coreContext.contactsManager.addListener(contactsUpdatedListener)
    }

    override fun onCleared() {
        callLogs.value.orEmpty().forEach(Module_Phone_GroupedCallLogData::destroy)
        missedCallLogs.value.orEmpty().forEach(Module_Phone_GroupedCallLogData::destroy)
        outgoingCallLogs.value.orEmpty().forEach(Module_Phone_GroupedCallLogData::destroy)
        displayCallLogs.value.orEmpty().forEach(Module_Phone_GroupedCallLogData::destroy)
        displayMissedCallLogs.value.orEmpty().forEach(Module_Phone_GroupedCallLogData::destroy)
        displayOutgoingCallLogs.value.orEmpty().forEach(Module_Phone_GroupedCallLogData::destroy)

        coreContext.contactsManager.removeListener(contactsUpdatedListener)
        coreContext.core.removeListener(listener)

        super.onCleared()
    }

    fun deleteCallLogGroup(callLog: Module_Phone_GroupedCallLogData?) {
        if (callLog != null) {
            for (log in callLog.callLogs) {
                coreContext.core.removeCallLog(log)
            }
        }

        updateCallLogs()
    }

    fun deleteAllCallLog() {
        callLogs.value?.let {
            for (callLog in it) {
                for (log in callLog.callLogs) {
                    coreContext.core.removeCallLog(log)
                }
            }
            updateCallLogs()
        }
    }

    fun deleteCallLogGroups(listToDelete: ArrayList<Module_Phone_GroupedCallLogData>) {
        for (callLog in listToDelete) {
            for (log in callLog.callLogs) {
                coreContext.core.removeCallLog(log)
            }
        }

        updateCallLogs()
    }

    fun sortCallLogsByName(name: String?) {
        var previousCallLogGroup: Module_Phone_GroupedCallLogData? = null
        val list = arrayListOf<Module_Phone_GroupedCallLogData>()
        for (callLog in coreContext.core.callLogs) {
            val remoteAddress = callLog.remoteAddress
            if (Module_Phone_LinphoneUtils.getDisplayName(remoteAddress).contains(name.toString())) {
                if (previousCallLogGroup == null) {
                    previousCallLogGroup = Module_Phone_GroupedCallLogData(callLog)
                } else if (previousCallLogGroup.lastCallLog.localAddress.weakEqual(callLog.localAddress) &&
                    previousCallLogGroup.lastCallLog.remoteAddress.weakEqual(callLog.remoteAddress)
                ) {
//                    if (TimestampUtils.isSameDay(previousCallLogGroup.lastCallLog.startDate, callLog.startDate)) {
//                        previousCallLogGroup.callLogs.add(callLog)
//                        previousCallLogGroup.lastCallLog = callLog
//                    } else {
                    list.add(previousCallLogGroup)
                    previousCallLogGroup = Module_Phone_GroupedCallLogData(callLog)
//                    }
                } else {
                    list.add(previousCallLogGroup)
                    previousCallLogGroup = Module_Phone_GroupedCallLogData(callLog)
                }
            }
        }
        if (previousCallLogGroup != null && !list.contains(previousCallLogGroup)) {
            list.add(previousCallLogGroup)
        }
        callLogsSortByName.value = list
        displayCallLogsSortByName.value = arrayListOf<Module_Phone_GroupedCallLogData>()

        if (callLogsSortByName.value!!.size > 500) {
            val subList = arrayListOf<Module_Phone_GroupedCallLogData>()
            subList.addAll(callLogsSortByName.value!!.subList(0, 500))
            displayCallLogsSortByName.value = subList
        } else {
            val subList = arrayListOf<Module_Phone_GroupedCallLogData>()
            subList.addAll(callLogsSortByName.value!!)
            displayCallLogsSortByName.value = subList
        }
    }

    private fun updateCallLogs() {
        Log.i("[Call Logs] updateCallLogs")
        callLogs.value.orEmpty().forEach(Module_Phone_GroupedCallLogData::destroy)
        missedCallLogs.value.orEmpty().forEach(Module_Phone_GroupedCallLogData::destroy)
        outgoingCallLogs.value.orEmpty().forEach(Module_Phone_GroupedCallLogData::destroy)
        displayCallLogs.value.orEmpty().forEach(Module_Phone_GroupedCallLogData::destroy)
        displayMissedCallLogs.value.orEmpty().forEach(Module_Phone_GroupedCallLogData::destroy)
        displayOutgoingCallLogs.value.orEmpty().forEach(Module_Phone_GroupedCallLogData::destroy)

        val list = arrayListOf<Module_Phone_GroupedCallLogData>()
        val missedList = arrayListOf<Module_Phone_GroupedCallLogData>()
        val outgoingList = arrayListOf<Module_Phone_GroupedCallLogData>()

        var previousCallLogGroup: Module_Phone_GroupedCallLogData? = null
        var previousMissedCallLogGroup: Module_Phone_GroupedCallLogData? = null
        var previousOutgoingCallLogGroup: Module_Phone_GroupedCallLogData? = null
        for (callLog in coreContext.core.callLogs) {
            if (previousCallLogGroup == null) {
                previousCallLogGroup = Module_Phone_GroupedCallLogData(callLog)
            } else if (previousCallLogGroup.lastCallLog.localAddress.weakEqual(callLog.localAddress) &&
                previousCallLogGroup.lastCallLog.remoteAddress.weakEqual(callLog.remoteAddress)
            ) {
//                if (TimestampUtils.isSameDay(previousCallLogGroup.lastCallLog.startDate, callLog.startDate)) {
//                    previousCallLogGroup.callLogs.add(callLog)
//                    previousCallLogGroup.lastCallLog = callLog
//                } else {
                list.add(previousCallLogGroup)
                previousCallLogGroup = Module_Phone_GroupedCallLogData(callLog)
//                }
            } else {
                list.add(previousCallLogGroup)
                previousCallLogGroup = Module_Phone_GroupedCallLogData(callLog)
            }

            if (Module_Phone_LinphoneUtils.isCallLogMissed(callLog)) {
                if (previousMissedCallLogGroup == null) {
                    previousMissedCallLogGroup = Module_Phone_GroupedCallLogData(callLog)
                } else if (previousMissedCallLogGroup.lastCallLog.localAddress.weakEqual(callLog.localAddress) &&
                    previousMissedCallLogGroup.lastCallLog.remoteAddress.weakEqual(callLog.remoteAddress)
                ) {
//                    if (TimestampUtils.isSameDay(previousMissedCallLogGroup.lastCallLog.startDate, callLog.startDate)) {
//                        previousMissedCallLogGroup.callLogs.add(callLog)
//                        previousMissedCallLogGroup.lastCallLog = callLog
//                    } else {
                    missedList.add(previousMissedCallLogGroup)
                    previousMissedCallLogGroup = Module_Phone_GroupedCallLogData(callLog)
//                    }
                } else {
                    missedList.add(previousMissedCallLogGroup)
                    previousMissedCallLogGroup = Module_Phone_GroupedCallLogData(callLog)
                }
            }

            if (Module_Phone_LinphoneUtils.isCallLogOutgoing(callLog)) {
                if (previousOutgoingCallLogGroup == null) {
                    previousOutgoingCallLogGroup = Module_Phone_GroupedCallLogData(callLog)
                } else if (previousOutgoingCallLogGroup.lastCallLog.localAddress.weakEqual(callLog.localAddress) &&
                    previousOutgoingCallLogGroup.lastCallLog.remoteAddress.weakEqual(callLog.remoteAddress)
                ) {
//                    if (TimestampUtils.isSameDay(previousOutgoingCallLogGroup.lastCallLog.startDate, callLog.startDate)) {
//                        previousOutgoingCallLogGroup.callLogs.add(callLog)
//                        previousOutgoingCallLogGroup.lastCallLog = callLog
//                    } else {
                    outgoingList.add(previousOutgoingCallLogGroup)
                    previousOutgoingCallLogGroup = Module_Phone_GroupedCallLogData(callLog)
//                    }
                } else {
                    outgoingList.add(previousOutgoingCallLogGroup)
                    previousOutgoingCallLogGroup = Module_Phone_GroupedCallLogData(callLog)
                }
            }
        }

        if (previousCallLogGroup != null && !list.contains(previousCallLogGroup)) {
            list.add(previousCallLogGroup)
        }
        if (previousMissedCallLogGroup != null && !missedList.contains(previousMissedCallLogGroup)) {
            missedList.add(previousMissedCallLogGroup)
        }
        if (previousOutgoingCallLogGroup != null && !outgoingList.contains(
                previousOutgoingCallLogGroup
            )
        ) {
            outgoingList.add(previousOutgoingCallLogGroup)
        }

        callLogs.value = list
        missedCallLogs.value = missedList
        outgoingCallLogs.value = outgoingList
        displayCallLogs.value = arrayListOf<Module_Phone_GroupedCallLogData>()
        displayMissedCallLogs.value = arrayListOf<Module_Phone_GroupedCallLogData>()
        displayOutgoingCallLogs.value = arrayListOf<Module_Phone_GroupedCallLogData>()

        // 通话记录最多显示500条
        if (callLogs.value!!.size > 500) {
            val subList = arrayListOf<Module_Phone_GroupedCallLogData>()
            subList.addAll(callLogs.value!!.subList(0, 500))
            displayCallLogs.value = subList

            val listToDelete = arrayListOf<Module_Phone_GroupedCallLogData>()
            listToDelete.addAll(callLogs.value!!.subList(500, callLogs.value!!.size))
            for (callLog in listToDelete) {
                for (log in callLog.callLogs) {
                    coreContext.core.removeCallLog(log)
                }
            }
        } else {
            val subList = arrayListOf<Module_Phone_GroupedCallLogData>()
            subList.addAll(callLogs.value!!)
            displayCallLogs.value = subList
        }

        if (missedCallLogs.value!!.size > 500) {
            val subList = arrayListOf<Module_Phone_GroupedCallLogData>()
            subList.addAll(missedCallLogs.value!!.subList(0, 500))
            displayMissedCallLogs.value = subList
        } else {
            val subList = arrayListOf<Module_Phone_GroupedCallLogData>()
            subList.addAll(missedCallLogs.value!!)
            displayMissedCallLogs.value = subList
        }

        if (outgoingCallLogs.value!!.size > 500) {
            val subList = arrayListOf<Module_Phone_GroupedCallLogData>()
            subList.addAll(outgoingCallLogs.value!!.subList(0, 500))
            displayOutgoingCallLogs.value = subList
        } else {
            val subList = arrayListOf<Module_Phone_GroupedCallLogData>()
            subList.addAll(outgoingCallLogs.value!!)
            displayOutgoingCallLogs.value = subList
        }
    }
}
